--
-- Author:      name
-- DateTime:    2018-05-28 15:57:48
-- Description: 游戏主逻辑

local skynet = require "skynet"
local log = require "Log"
local config = require "configquery"
local Timer = require "timer"
local FSM = require "fsm"
local NodeMessage = require "NodeMessage"
local Universal = require "Universal"
local json = require "cjson"
require "common"


local mix_array = mix_array
local table_clone = table_clone
local floor = math.floor
local four_five = math.four_five
local random = math.random


local Machine = class("Machine")

function Machine:ctor(tableid,rule)
	self.close = false --关闭游戏
	self.nodeMessage = NodeMessage.new()
	--共用类
	self.universal = Universal.new()

	self.player_list = {} --玩家列表
	self.seat_list = {} --座位列表
	self.tableid = tableid --桌子id

	self.gameid = getGameIdbyTable(tableid)
	self.roomid = getRoomType(tableid)
	local cfgname = getGameRoomConfig(self.gameid)
	local roomcfg = config[cfgname][self.roomid]

	--配置信息
	self.maxSeatNum = roomcfg.player_num --最大座位数
	self.bottomNum = roomcfg.bottom_score * 0.01 --底分
	self.tipRate = roomcfg.tip * 0.01 --服务费比
	self.incomeRate = 1 - self.tipRate --收入占比
	self.minChip = roomcfg.min_coin --入场最低分
	self.topChip = roomcfg.max_coin --入场最高分
	self.maxOperTimeoutNum = 3 --最多操作超时次数

	--状态时间
	self.stateTime = {	
		rest = 5,		--休息时间
		start = 20,		--开始(下注)
		throw = 6,      --去牌头
		throw_tail = 5, --去牌尾	
		card = 30,	    --选择比牌操作时间		
		settlement = 4, --结算时间
	}
	
	--加注列表
	self.addChipList = {
		[0.01]= {'0.02','0.05','0.1'},
		[1]= {'2','5','10'},
		[5]= {'10','20','50'},
		[10]= {'20','100','200'},
	}
	self.chipList = self.addChipList[self.bottomNum]
	--配置信息
	self.maxRound = 80 --最大轮数
	self.curRound = 0 --当前轮
	self.playerNum = 0 --参与下注的人数

	self.handlerStateTime = nil --定时器句柄
	self.tbBeforeStart = {} --开始游戏前所捅有筹码，用于牌局记录
	self.allBetChip = 0 --所有玩家总共下注
	self.operStartTime = 0 --当前状态的开始时间
	
	self.gmcards = {} --配牌列表
	self.tbCheatNum = {} --配牌标记
	self.paijuid = 0 --牌局ID
	self.closeHandler = nil --维护时关游戏定时器
	self.rule = rule


	--位置id 1闲 2和 3庄 4闲对 5庄对
	self.poolName = {
		player = 1,
		tie = 2,
		banker = 3,
		player_pairs = 4,
		banker_pairs = 5,
	}
	self.maxPoolid = 5
	self.poolAllBet = {} --已下注总分
	self.poolPlayerAllBet = {} --各个池所有玩家的下注总分
	self.poolPlayerChipList = {} --各个池所有玩家的下注筹码列表
	self.poolRate = {1,8,0.95,11,11} --倍数
	self.poolChipList = {} --筹码列表
	self.winList = {} --赢的池id记录

	self.playerCards = {} --闲牌
	self.bankerCards = {} --庄牌
	self.tbPlayerWinChip = {} --各玩家所赢的金币
	self.winPoolid = {} --赢的池id
	self.tbPlayerAllBet = {} --玩家总下注

	self.stock = {} --库存
	-- self:getStock()
	print("self.stock_____",self.stock)

	--状态
	--休息，开始， 玩家操作，发牌，结算
	--state1 --eventName --state2 --callback
	self.gameStateTransitionTable = {
		{"rest", 		"to_throw_top",			"throw_top", 		function() self:onThrowTop() end },
		{"settlement", 	"to_throw_tail",		"throw_tail", 		function() self:onThrowTail() end },
		{"throw_tail", 	"to_rest",				"rest", 		function() self:onRest() end },
		{"rest", 		"to_start", 			"start", 		function() self:onStart() end },
		{"throw_top", 	"throw_to_start",		"start", 		function() self:onStart() end },
		{"start", 		"to_card",				"card", 		function() self:onCard() end },
		{"card", 		"to_settlement",		"settlement", 	function() self:onSettlement() end },
		{"settlement", 	"to_rest", 				"rest", 		function() self:onRest() end },
	}
	--计时器
	self.timer = Timer:new()
	--状态机
	self.fsm = FSM.new(self.gameStateTransitionTable)
	self:reset()
end
---------------------------------------------------------
-- private
---------------------------------------------------------
--重置数据
function Machine:reset()

	self.playerNum = 0

	self.tbBeforeStart = {}
	self.poolAllBet = {} --已下注总分
	self.poolPlayerAllBet = {} --所有玩家的下注分
	self.poolPlayerChipList = {}
	self.poolChipList = {} --筹码列表	
	self.playerCards = {} --闲牌
	self.bankerCards = {} --庄牌	
	--玩家自身状态
	for k,v in pairs(self.player_list) do 
		v.playing = false	
	end
	for i=1,self.maxPoolid do 
		self.poolAllBet[i] = 0
		self.poolPlayerAllBet[i] = {}
		self.poolChipList[i] = {}		
		self.poolPlayerChipList[i] = {}
	end

	self.allBetChip = 0
	self.operStartTime = 0
	self.winPoolid = {} --赢的池id
	self.tbPlayerWinChip = {} --各玩家所赢的金币
	self.tbPlayerAllBet = {} --玩家总下注
end

--状态定时器
function Machine:setTime(time,callback,loop,param)
	if self.handlerStateTime then 
		self.timer:unregister(self.handlerStateTime)
		self.handlerStateTime = nil	
	end
	if not time then 
		return 
	end
	self.handlerStateTime = self.timer:register(time , param, callback,loop)	
end

--更新大厅中传来的玩家数据
function Machine:updateProperty(playerid,data)
	local player = self.player_list[playerid]
	if not player then 
		return 
	end
	for k,v in pairs(data) do 
		player[k] = v
	end
	-- local seatPlayer = self:getSeatPlayer(player)
	-- local data = {zjh_nt_seat_change = {
	-- 	tableid = self.tableid,
	-- 	seatid = seatid,
	-- 	seat_player = seatPlayer,
	-- 	leave = false,
	-- }}
	-- self:sendToAll(data)
end

--更新人数
function Machine:updatePlayerNum( )
	local c = self:getTablePlayerNum()
	self.nodeMessage:sendGlobalService('tablestate', 'set', self.tableid, c)
end

--桌子人数
function Machine:getTablePlayerNum()
	local c = 0
	for k,v in pairs(self.player_list) do
		c = c + 1
	end
	return c
end

--离线清除
function Machine:removePlayer()
	for k,v in pairs(self.player_list) do 	
		if v.disconnect or v.chip < self.minChip  then 	
			if  v.chip < self.minChip then 
				local data = {nt_kick_table = {
					playerid = k,
					content = '金币不足请离场！',
				}}
				self:sendMessage(k,data)
			end			
			--设置玩家所在桌子id为0	
			self:sendGate(v, 'update_tableid', 0)
			self:sitUp(k)
			self.player_list[k] = nil
			print("百家乐踢走掉线 o#######",k)
		end
	end
end

--离线清除
function Machine:removeDisconnect()
	for k,v in pairs(self.player_list) do 
		if v.disconnect then 	
			self:sitUp(k)
			self.player_list[k] = nil
			--清除玩家所在桌子id
			self:sendGate(v, 'update_tableid', 0)	
			print("踢走离线#######",k)		
		end
	end
end

--取seatplayer
function Machine:getSeatPlayer(player)
	local seatPlayer = {}
	seatPlayer.seatid = player.seatid
	seatPlayer.playerid = player.playerid
	seatPlayer.nick = player.nick
	seatPlayer.chip = ""..player.chip
	seatPlayer.silver = player.silver
	seatPlayer.icon = player.icon
	seatPlayer.viplevel = player.viplevel
	seatPlayer.level = player.level

	seatPlayer.playing = player.playing
	seatPlayer.bet_chip = tostring(self.tbPlayerAllBet[playerid] or 0)

	return seatPlayer
end

--取当前正在局里玩家数
function Machine:getPlayingNum()
	local num = 0
	for k, v in pairs(self.player_list) do 
		if self:isPlaying(v) then 
			num = num + 1
		end
	end	
	return num 
end

--是否正在局中玩
function Machine:isPlaying(player)
	if player and player.playing  then 
		return true
	end
	return false
end

--通过座位取玩家
function Machine:getPlayerBySeat(seatid)
	local playerid = self.seat_list[seatid]
	if not playerid then return end
	return self.player_list[playerid]
end


---------------------------------------------------------
-- 发送消息
---------------------------------------------------------
--需要返回的请求
function Machine:callGate(player,cmd,data)
	return self.nodeMessage:callGate(player.nodename,player.playerid,cmd,data)
end

function Machine:sendGate(player,cmd,data)
	self.nodeMessage:sendGate(player.nodename,player.playerid,cmd,data)
end

function Machine:sendMessage(playerid,data)
	local player = self.player_list[playerid]
	if not player or player.disconnect then 
		return
	end	
	self.nodeMessage:broadcastGate(player.nodename,{playerid},data)
end

function Machine:sendToAll(data)
	local playerList = {}	
	for k,v in pairs(self.player_list) do 
		if not v.disconnect  then 
			table.insert(playerList,k)
		end
	end
	self.nodeMessage:broadcastAllGate(playerList, data)
end

function Machine:sendToOther(playerid,data)
	local playerList = {}
	for k,v in pairs(self.player_list) do 
		if (not v.disconnect and k ~= playerid) then 	
			table.insert(playerList,k)
		end
	end
	self.nodeMessage:broadcastAllGate(playerList, data)
end
function Machine:reconnect(playerid)
	-- return self.tbMessage[playerid]
end


---------------------------------------------------------
-- 状态
---------------------------------------------------------

--休息
function Machine:onRest()
	print("_______rest")
	self.operStartTime = os.time()

	--重置数据
	self:reset()
	self:ntRest()
	self:removePlayer()

	local callback = function ( ... )
		--[[
			1.取牌，大于0小于7张牌 扔牌尾
			2.等于0洗牌 扔牌头7张
			3
		--]]
		local cardNum = self.rule:getLeftCardCount()
		print("_________cardNum __",cardNum)
		if cardNum == 0 then 
			--洗牌
			self.fsm:fire("to_throw_top")
		else
			--正常发牌
			self.fsm:fire("to_start")
		end
		
	end
	self:setTime(self.stateTime.rest,callback)

end

--去牌头
function Machine:onThrowTop()
	print("________throw_top")
	self.operStartTime = os.time()		
	local callback = function ()
		self.fsm:fire("throw_to_start")
	end
	self:setTime(self.stateTime.throw,callback)
	local cardTop
	--洗牌
	self.rule:shuffle()
	cardTop = self.rule:getHeadCard()	
	self.curRound = 0

	self.winList = {}
	local data = {bjl_nt_throw={
 		tableid = self.tableid,	
 		time = self.stateTime.throw,
 		card_top_list = cardTop,
	}}
	print(data)
	self:sendToAll(data)
end

--去牌尾
function Machine:onThrowTail()
	print("________throw_tail")
	self.operStartTime = os.time()	
	local callback = function ()
		self.fsm:fire("to_rest")
	end
	self:setTime(self.stateTime.throw_tail,callback)
	 
	--去牌尾
	local cardTail = self.rule:getLeftCard()
	self.rule:clearCard()
	local data = {bjl_nt_throw_tail={
 		tableid = self.tableid,	
 		time = self.stateTime.throwTail,
 		card_tail_list = cardTail,
	}}
	print(data)
	self:sendToAll(data)
	-- skynet.exit();
end

--开始
function Machine:onStart()
	print("_______start")	
	self.operStartTime = os.time()		
	--开始下注
	local callback = function ()
		--停止下注
		self.fsm:fire("to_card")
	end
	self:setTime(self.stateTime.start,callback)
	self.paijuid = getRoundId(self.tableid)


	self:ntStart()
	-- self:ntCardToRoot()
end

--发牌
function Machine:onCard()
	print("_______card")	
	self.operStartTime = os.time()	
	local callback = function ()
		self.fsm:fire("to_settlement")
	end
	self:setTime(self.stateTime.card,callback)
	for k,v in pairs(self.player_list) do 
		self.tbBeforeStart[k] = v.chip
	end

	--扔一张牌
	local card = self.rule:getFoldCard()
	--取闲，庄牌
	self.playerCards,self.bankerCards = self.rule:getPlayAndBankCards()
	--检查库存
	self:checkStock()

	local data = {
		bjl_nt_card = {
			tableid = self.tableid,
			time = self.stateTime.card,
			player_cards = self.playerCards,
			banker_cards = self.bankerCards,
			card = card,
		}
	}
	print(data)
	self:sendToAll(data)
end

--结算
function Machine:onSettlement()
	print("_______settlement")
	self.operStartTime = os.time()	

	local callback = function()
		local cardNum = self.rule:getLeftCardCount()
		print("______cardNum__________",cardNum)
		if cardNum > 0 and cardNum < self.rule:geTailNum() then 
			--扔牌尾	
			self.fsm:fire("to_throw_tail")			
		else
			self.fsm:fire("to_rest")
		end
	end		
	self:setTime(self.stateTime.settlement, callback)
	local reason = self.universal:getReasonId('bjl_js')
	local money

	local result = self.rule:compareCard(self.playerCards,self.bankerCards)
	if result == 1 then
		--闲
		table.insert(self.winPoolid,self.poolName.player)
		table.insert(self.winList,self.poolName.player)
	elseif result == -1 then 
		--庄
		table.insert(self.winPoolid,self.poolName.banker)
		table.insert(self.winList,self.poolName.banker)
	else
		--和
		table.insert(self.winPoolid,self.poolName.tie)
		table.insert(self.winList,self.poolName.tie)
	end
	if self.rule:existPair(self.playerCards) then 
		table.insert(self.winPoolid,self.poolName.player_pairs)
		table.insert(self.winList,self.poolName.player_pairs)
	end
	if self.rule:existPair(self.bankerCards) then 
		table.insert(self.winPoolid,self.poolName.banker_pairs)
		table.insert(self.winList,self.poolName.banker_pairs)
	end
	self.curRound = self.curRound + 1
	local data = {bjl_nt_end={
 		tableid = self.tableid,	
 		time = self.stateTime.settlement,
 		win_pools = self.winPoolid, 	
 		cur_round = self.curRound,	
	}}

	local poolbet
	for k,v in pairs(self.player_list) do 
		self.tbPlayerWinChip[k] = 0
		if v.playing then 
			for poolid = 1 , self.maxPoolid do 
				v.tbPoolBet[poolid] = self.poolPlayerChipList[poolid][k] or {}
			end			
			
			for _,poolid in pairs(self.winPoolid) do 
				poolbet = self.poolPlayerAllBet[poolid][k] or 0
				if poolbet > 0 then 
					self.tbPlayerWinChip[k] = self.tbPlayerWinChip[k] + poolbet*(1+self.poolRate[poolid])
				end
			end
			data.bjl_nt_end.win_chip = self.tbPlayerWinChip[k]				
		end
		data.bjl_nt_end.seat_player = self:getSeatPlayer(v)
		if self.tbPlayerWinChip[k] > 0 then
			money = self:callGate(v, 'change_money', self.tbPlayerWinChip[k], reason)			
		end
		if money then 
			v.chip = money
		end
		self:sendMessage(k,data)

	end
	--更新库存
	self:setStock()
	--牌局记录
	self:paijuRecord()
end

---------------------------------------------------------
-- public
---------------------------------------------------------
--取桌子id
function Machine:getTableId()
	return self.tableid
end

--取玩家
function Machine:getPlayer(playerid)
	if not playerid then return nil end
	return self.player_list[playerid]
end

--加入玩家
function Machine:addPlayer(player)
	self.player_list[player.playerid] = player
	player.tbPoolBet = {} --最后一场各池下注额
end

--取玩家座位id
function Machine:getPlayerSeatId(playerid)
	for k, v in pairs(self.seat_list) do 
		if v == playerid then
			return k
		end
	end
	return nil
end


--坐下
function Machine:sitDown( playerid )
	local tbSeat = {}
	for id=1,self.maxSeatNum do 
		local seat_userid = self.seat_list[id]
		if not seat_userid or seat_userid == 0 then 
			table.insert(tbSeat,id)
		end
	end
	mix_array(tbSeat) --随机位置
	local seatid
	if #tbSeat > 0 then 
		seatid = tbSeat[1]
	else
		return false
	end
	local player = self.player_list[playerid]
	if player then
		self.seat_list[seatid] = playerid
		player.seatid = seatid
	end
	--print(player)
	local seatPlayer = self:getSeatPlayer(player)
	local data = {bjl_nt_seat_change = {
		tableid = self.tableid,
		seatid = seatid,
		seat_player = seatPlayer,
		playerid = playerid,
		leave = false,
	}}
	self:sendToOther(playerid,data)
	self:updatePlayerNum()
	return true
end

--离座
function Machine:sitUp(playerid)
	local seatid = 0
	if not playerid or playerid <=0 then
		return
	end
	local player = self.player_list[playerid]
	if not player then
		return
	end
	self.player_list[playerid] = nil
	self:updatePlayerNum()
end

--取桌子状态
function Machine:getTableStatus(playerid)
	local seatPlayer
	local player = self.player_list[playerid]
	seatPlayer = self:getSeatPlayer(player)
		
	local status = {		
		tableid = self.tableid,
		seat_player = seatPlayer,
		config = self:getConfig(),
		bet_pool_list = self:getPoolList(),
		all_chip = tostring(self.allBetChip),
		cur_round = self.curRound,
		win_list = self.winList,		
		player_cards = self.playerCards,
		banker_cards = self.bankerCards,
		time = self:getOperTime(), --当前操作所剩余时间
		people_num = self:getTablePlayerNum(),
		state = self:getState(),
	}	

	print("Table status################",status)	
	return status
end

--请求下注
function Machine:onPlayerBet(playerid,args)
	local state = self:getState()
	if state ~= 'start' then 
		return GetErrorTable(11)
	end		
	local player = self.player_list[playerid]
	local addChip = args.add_chip
	local poolid = args.poolid
	local reason = self.universal:getReasonId('bjl_xz')
	local money
	local hasBetChip = 0
	local ok = false
	if tonumber(addChip) > player.chip then 
		return GetErrorTable(12)
	end
	
	for i=1,self.maxPoolid do 
		if poolid == i then 
			ok = true
			break
		end
	end
	if not ok then 
		return GetErrorTable(13)
	end
	ok = false

	for k,v in pairs(self.chipList) do 
		if addChip == v then 
			ok = true
			break
		end
	end
	if not ok then 
		return GetErrorTable(13)
	end	

	money = self:callGate(player, 'change_money', -addChip, reason)
	if money then 
		player.chip = money
		if not self.poolPlayerAllBet[poolid][playerid] then 
			self.poolPlayerAllBet[poolid][playerid] = 0
		end
		if not self.poolPlayerChipList[poolid][playerid] then 
			self.poolPlayerChipList[poolid][playerid] = {}
		end
		self.poolPlayerAllBet[poolid][playerid] = self.poolPlayerAllBet[poolid][playerid] + addChip
		table.insert(self.poolChipList[poolid],addChip)
		table.insert(self.poolPlayerChipList[poolid][playerid],addChip)
		self.poolAllBet[poolid] = self.poolAllBet[poolid] + addChip
		self.allBetChip = self.allBetChip + addChip
		local chip
		for i=1,self.maxPoolid do 
			chip = self.poolPlayerAllBet[i][playerid] 
			if chip then 
				hasBetChip = hasBetChip + chip
			end
		end
		self.tbPlayerAllBet[playerid] = hasBetChip
		player.playing = true

		--马上推送给别的玩家
		local data = {
			bjl_nt_other_bet = {
				tableid = self.tableid,				
				pool_chip_list = {{
					id = poolid,
					all_bet = self.poolAllBet[poolid],
					my_bet = self.poolPlayerAllBet[poolid][playerid],
					chip_list = {addChip},
				}}				
			}
		}		
		self:sendToOther(playerid,data)

		return {
			bet_chip = hasBetChip,
			pool_chip_list = {{
				id = poolid,
				all_bet = self.poolAllBet[poolid],
				my_bet = self.poolPlayerAllBet[poolid][playerid],
				chip_list = {addChip},
			}}
		}
	end
	return GetErrorTable(14)

end

--重复上场下注
function Machine:onPlayerRebet(playerid)
	local state = self:getState()
	if state ~= 'start' then 
		return GetErrorTable(11)
	end	
	local player = self.player_list[playerid]
	local addChip
	local allBetChip = 0
	local remainChip = player.chip
	local poolChipList = {}
	local reason = self.universal:getReasonId('bjl_xz')
	local money
	local hasBetChip = 0
	local tbPoolBet

	for poolid = 1, self.maxPoolid do 
		tbPoolBet = player.tbPoolBet[poolid] or {}		
		for _,strChip in pairs(tbPoolBet) do 
			poolChipList[poolid] = {}
			addChip = tonumber(strChip)
			if addChip and addChip > 0 and remainChip > 0 then 
				if addChip < remainChip then 
					allBetChip = allBetChip + addChip
					remainChip = remainChip - addChip
					table.insert(poolChipList[poolid],addChip)
				else
					break
				end
			end
		end
	end
	if allBetChip <= 0 then 
		return 
	end
	money = self:callGate(player, 'change_money', -allBetChip, reason)
	if money then 
		player.chip = money
		local poolBetList = {}
		for poolid ,chipList in pairs(poolChipList) do 
			if not self.poolPlayerAllBet[poolid][playerid] then 
				self.poolPlayerAllBet[poolid][playerid] = 0
			end
			if not self.poolPlayerChipList[poolid][playerid] then 
				self.poolPlayerChipList[poolid][playerid] = {}
			end		
			for _,addChip in pairs(chipList) do 	
				self.poolPlayerAllBet[poolid][playerid] = self.poolPlayerAllBet[poolid][playerid] + addChip
				table.insert(self.poolChipList[poolid],addChip)
				table.insert(self.poolPlayerChipList[poolid][playerid],addChip)
				self.poolAllBet[poolid] = self.poolAllBet[poolid] + addChip
				self.allBetChip = self.allBetChip + addChip
			end
			poolBetList.id = poolid
			poolBetList.chip_list =  chipList
			poolBetList.all_bet =  self.poolAllBet[poolid]
			poolBetList.my_bet =  self.poolPlayerAllBet[poolid][playerid]
		end		
		player.playing = true
		local chip
		for i=1,self.maxPoolid do 			
			chip = self.poolPlayerAllBet[i][playerid] 
			if chip then 
				hasBetChip = hasBetChip + chip
			end
		end
		self.tbPlayerAllBet[playerid] = hasBetChip
		--马上推送给别的玩家
		local data = {
			bjl_nt_other_bet = {
				tableid = self.tableid,				
				pool_chip_list = {poolBetList},			
			}
		}
		self:sendToOther(playerid,data)

		return {
			bet_chip = hasBetChip,			
			pool_chip_list = {poolBetList},
		}
	end
	return GetErrorTable(12)
end

--查看所剩下的牌数
function Machine:onRemainCard(playerid)
	local state = self:getState()
	if state == 'throw_top' then 
		return GetErrorTable(11)
	end
	local cards = self.rule:getEachCardLeftNum()
	local color
	local point
	local spade = {}
	local redheart = {}
	local club = {}
	local block = {}
	for card,num in pairs(cards) do 
		color = card & 0xf0
		point = card & 0x0f
		if color == 0x0 then 
			spade[point] = num
		end
		if color == 0x10 then 
			redheart[point] = num
		end
		if color == 0x20 then 
			club[point] = num
		end
		if color == 0x30 then 
			block[point] = num
		end
	end
	return {spade_cards = spade,
			redheart_cards = redheart,
			club_cards = club,
			block_cards = block,
	}
end

-------------------------------------------------------------------------------
-- 推送消息
-------------------------------------------------------------------------------
function Machine:ntStart()
	print("__________bjl_start")
	local data = {bjl_nt_start={
 		tableid = self.tableid,	
 		paijuid = self.paijuid,
 		time = self.stateTime.start, 		
	}}
	print(data)
	self:sendToAll(data)
end

function Machine:ntRest()
	local data = {bjl_nt_rest={
 		tableid = self.tableid,	
	}}
	self:sendToAll(data)	

end

--推送牌给机器人
function Machine:ntCardToRoot()
	
end

----------------------------------
-- 数据操作
----------------------------------
function Machine:calldb(cmd,...)
	return skynet.call('dbmgr_service','lua',cmd,...)	
end

function Machine:senddb(cmd,...)
	skynet.send('dbmgr_service','lua',cmd,...)	
end

--取库存表
function Machine:getStock()
	local stock = self:calldb('get_stock',self.gameid)
	if not next(stock) then 
		stock = {
			gameid=self.gameid,
			pool = 0,
			bottom = 1000,
			top = 100000,
			tip = 0,
		}
		self:calldb('add_stock',stock)		
		stock = self:calldb('get_stock',self.gameid)
	end
	self.stock = stock	
end

function Machine:setStock()
	--机器人库存更新
	local system_earn,tip = self:robotSettlement()		
	if system_earn ~= 0 then 
		self.stock.pool = self.stock.pool + system_earn
		self.stock.tip = self.stock.tip + tip
		self:senddb('update_stock',self.stock)	
	end
end

--计算机器人输赢
function Machine:robotSettlement()
	local systemEarn = 0 --系统赢的钱
	local playerEarn = 0
	local tip = 0 --服务费
	local winPoolid = {}
	local poolbet

	local result = self.rule:compareCard(self.playerCards,self.bankerCards)
	if result == 1 then
		--闲
		table.insert(winPoolid,self.poolName.player)
	elseif result == -1 then 
		--庄
		table.insert(winPoolid,self.poolName.banker)
	else
		--和
		table.insert(winPoolid,self.poolName.tie)
	end
	if self.rule:existPair(self.playerCards) then 
		table.insert(winPoolid,self.poolName.player_pairs)
	end
	if self.rule:existPair(self.bankerCards) then 
		table.insert(winPoolid,self.poolName.banker_pairs)
	end
	
	for k,v in pairs(self.player_list) do 		
		if v.playing and not v.robot then 	
			playerEarn = 0				
			for _,poolid in pairs(winPoolid) do 
				poolbet = self.poolPlayerAllBet[poolid][k] or 0
				if poolbet > 0 then 
					playerEarn = playerEarn + poolbet*(1+self.poolRate[poolid])
				end
			end
			systemEarn = systemEarn + (playerEarn - self.tbPlayerAllBet[k])
		end
	end

	if systemEarn > 0 then 
		systemEarn = self.universal:setChip(systemEarn * (1-self.tipRate))
		tip = self.universal:setChip(systemEarn * self.tipRate)
	elseif systemEarn < 0 then
		systemEarn = self.universal:setChip(systemEarn)
	end
	return systemEarn, tip
end

--检查库存
function Machine:checkStock()
	--1.发牌后预先开牌,机器人和普通人间输赢计算 
	--2.如果库存够赔付正常开牌
	--3.如果库存不够换牌的位置再计算
	self:getStock()
	if not self.stock or not next(self.stock) then --无库存控制
		return false
	end 
	print("____2222222__库存______self.stock_______",self.stock)
	local stock = self.stock
	local function get_earn()	
		local pool = stock.pool
		local bottom = stock.bottom
		local systemEarn = self:robotSettlement()	
		if systemEarn == 0 then --无人在打
			return true
		end
		if pool <= bottom then --库存低于底线时一率杀
			if systemEarn >= 0 then 
				return true
			end
			return false
		end
		--库存 + 机器人输赢  > 0 可开牌
		local earn = pool  + systemEarn
		if earn > 0 then
			print("__2222222222222______pool___",pool,self.stock)
			return true
		end
		return false
	end

	local res = get_earn()
	if res then
		return true
	end
	print("___________第一道防线__修改结果__")
	--把牌放回去
	self.rule:addToCardCase(self.playerCards)
	self.rule:addToCardCase(self.bankerCards)
	local resNum = self.rule:compareCard(self.playerCards,self.bankerCards)
	if resNum == 1 then --闲赢
		--改庄赢
		self.playerCards,self.bankerCards = self.rule:getWantCard(self.rule.wantCardTag.BANK_WIN,true,true)
	elseif resNum == -1 then --庄赢
		self.playerCards,self.bankerCards = self.rule:getWantCard(self.rule.wantCardTag.PLAY_WIN,true,true)
	elseif resNum == 0 then --和赢
		self.playerCards,self.bankerCards = self.rule:getWantCard(self.rule.wantCardTag.PLAY_WIN,false,false)
	end
	local res = get_earn()
	if res then
		return true
	end
	print("___________第二道防线__修改结果为和__")
	self.rule:addToCardCase(self.playerCards)
	self.rule:addToCardCase(self.bankerCards)
    --和
	self.playerCards,self.bankerCards = self.rule:getWantCard(self.rule.wantCardTag.TIE)
	local res = get_earn()
	if res then
		return true
	end
	print("___________第三道防线__修改结果为和无对__")
	self.rule:addToCardCase(self.playerCards)
	self.rule:addToCardCase(self.bankerCards)	
	self.playerCards,self.bankerCards = self.rule:getWantCard(self.rule.wantCardTag.TIE,true,true)
	local res = get_earn()
	if res then
		return true
	end
	log.error('___error_________________库存控制失败了_______',self.paijuid)
	
	return false
end

-------------------------------------------------------------------------------
-- 牌局记录
-------------------------------------------------------------------------------
function Machine:paijuRecord()
	local playerid 
	local win 
	local chip
	local beforeStart
	local cardType
	local winChip = 0
	local poolPlayerAllBet --各池所下筹码
	local playerPoint = self.rule:getPoint(self.playerCards)
	local bankerPoint = self.rule:getPoint(self.bankerCards)
	local strResult
	local betNum
	win = 0
	strResult = '庄赢'
	if playerPoint > bankerPoint then 
		strResult = '闲赢'
	elseif playerPoint == bankerPoint then 
		strResult = '和赢'
	end
	strResult = '闲' .. playerPoint .. '点'..'庄'..bankerPoint..'点'..strResult

	beforeStart = self.tbBeforeStart[playerid]
	for k,v in pairs(self.player_list) do 
		if v.playing then 
			playerid = v.playerid		
			seatid = v.seatid
			win = 0	
			winChip = self.tbPlayerAllBet[playerid] - self.tbPlayerWinChip[playerid]		
			if winChip <= 0 then 
				win = 1
			end
			poolPlayerAllbet = {}
			for i=1,self.maxPoolid do 
				betNum = self.poolPlayerAllBet[i][playerid] or 0
				table.insert(poolPlayerAllbet,betNum)
			end

		    --牌局记录写到redis 
			local record = {
				_type = "playercard" .. self.gameid, --记录类型
				mid = playerid, --玩家id
				appid = v.appid, --appid
				channelid = v.channelid, --渠道id			
				gameid = self.gameid, --游戏id
				levelid = self.roomid, --房间id
				tableid = self.tableid, --桌子id
				cardid = self.paijuid, --牌局id
				before = self.tbBeforeStart[playerid], --开始前所拥有的金币
				after = v.chip, --结束后有拥有的金币
				iswin = win, --玩家输赢
				optnum = winChip, --玩家赢钱数（赢钱 - 下注 - 服务费）
				updatetime = os.time(),	--结束时间		
				playercards = self.playerCards, --闲牌		
				bankercards = self.bankerCards, --庄牌
				poolbet_list = poolPlayerAllbet, --玩家在各池所下筹码 1闲 2和 3庄 4闲对 5庄对				
				poolwin_list = self.winPoolid, --赢的位置id列表
				result = strResult, --牌输赢描述
				-- cardtype = cardType, --牌型
			}
			send_redis({ "rpush", "logs:queue_list", json.encode(record) }, 1)
		end
	end
	

end






-----------------------------------------------------------------------------------
----------------------------------
-- 数据操作
----------------------------------
--当前操作所剩余的时间
function Machine:getOperTime()
	local time = self.stateTime[self:getState()] - (os.time() - self.operStartTime)
	if time < 0 then 
		time = 0
	end
	return time
end

--当前状态
function Machine:getState()
	return self.fsm:get()
end

--状态对应的数字
function Machine:getStateNum()
	local state = self:getState()
	for k, v in pairs(self.gameStateTransitionTable) do 
		if state == v[1] then 
			return k
		end
	end
	return 
end

--桌子相关配置
function Machine:getConfig()
	return {
		bottom_num	= tostring(self.bottomNum),	-- 底分		
		max_round   = self.maxRound, 	--最大轮数
		time_rest = self.stateTime.rest,
		time_start = self.stateTime.start,
		time_bet = self.stateTime.bet,
		time_card = self.stateTime.card,
		time_end = self.stateTime.settlement,		
		chip_list = self.chipList,
	}
end

--取下注池数据
function Machine:getPoolList(playerid)
	local poolList = {}
	for i=1,self.maxPoolid do 
		local pool = {}
		pool.id = i
		pool.all_bet = self.poolAllBet[i]
		pool.my_bet = self.poolPlayerAllBet[i][playerid]
		pool.rate = self.poolRate[i]
		pool.chip_list = self.poolChipList[i]
		table.insert(poolList,pool)
	end	
	return poolList
end

--取牌
function Machine:getCard(playerid,num)
	local tbCard = {}
	local playerCard = self.gmcards[playerid] 
	local delCard = {}
	if playerCard and #playerCard>0 and self.tbCheatNum[playerid] > 0 then --有配牌		
		self.tbCheatNum[playerid] = self.tbCheatNum[playerid] - 1
		if self.tbCheatNum[playerid] == 0 then
			self.gmcards[playerid] = {}
		end	
		if num == 1 then 
			table.insert(tbCard,playerCard[5])
		else
			for i=1,num do 
				table.insert(tbCard,playerCard[i])
			end
		end
		return tbCard
	end

	return self.rule:getCard(num)
end

function Machine:setGmCard(playerid,cards,repeatNum)

	self.tbCheatNum[playerid] = repeatNum or 0
	if repeatNum  == 0 then
		self.gmcards[playerid] = {}
	else
		self.gmcards[playerid] = cards
	end
	print("_______cards#################___________________",cards)
end

--进入桌子
function Machine:enterTable(playerid,player_info,open_card)
	print('玩家进入牌桌>>>>>>>>>>>',player_id,self.tableid,open_card)
	
end

--离开桌子
function Machine:leaveTable(playerid)
	print('玩家离开牌桌>>>>>>>>>>>',playerid,self.tableid)
	self:sitUp(playerid)
end

--掉线处理
function Machine:disconnect(playerid)
	print('玩家掉线>>>>>>>>>>>',playerid,self.tableid)
	local player = self.player_list[playerid]
	--旁观者掉线马上踢出大厅
	if not player.playing and player.disconnect then 
		print("########在旁观玩家中直接踢走")	
		self:sendGate(player, 'update_tableid', 0)
		self:sitUp(playerid)
		return true
	end	
	return false
end

--关闭服务
function Machine:exit()
	self.nodeMessage:sendService('.proxy','clear_table',self.tableid)
	skynet.fork(function()
		skynet.sleep(200)
		skynet.exit()
	end)
end

--安全关服务
function Machine:setClose(close)

	--定时踢出所有玩家后，关服
	self.close = close
	if not self.closeHandler then 
		self.timer:unregister(self.closeHandler)
		self.closeHandler = nil
	end
	if close then 
		local maxDelay = 5*60 --最大的等待时间
		local delay = 0
		local callback = function()
			delay = delay + 1
			if delay > maxDelay then
				self.fsm:fire('to_rest') 
				self.fsm:set('rest')
				self:onRest()
			end
			if self:getState() ~= "rest" and self:getState() ~= "wait" then 
				return
			end
			for k,v in pairs(self.player_list) do 
				if close then 				
					local data = {nt_kick_table = {
						playerid = k,
						content = '游戏正在维护！',
					}}
					self:sendMessage(k,data)	
					--设置玩家所在桌子id为0	
					self:sendGate(v, 'update_tableid', 0)
					self:sitUp(k)
					self.player_list[k] = nil
				end
			end		
			self.timer:unregister(self.closeHandler)			
			self:exit()
		end
		--1局玩完后关游戏
		self.closeHandler = self.timer:register(1 , nil, callback,true)
	end	
end

----------------------------------------------------------------------------------------------
---------开始游戏
---------------------------------------------------------------------------------------------- 
function Machine:start()
	self.fsm:set("settlement")
	self.fsm:fire("to_rest")
end

return Machine